package ru.hh.school;

import ru.hh.school.PrivateMessage;
import ru.hh.school.exceptions.InnerChatException;
import ru.hh.school.persistence.DataRepository;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

public class SuperBlockingQueue {
    private final int maxNumber;
    private final DataRepository dataRepository;
    private final int ownerId;
    private final List<String> queue;
    private final List<PrivateMessage> privateQueue;
    private boolean databaseNotEmpty;
    private long lastPrivateMessageId;

    public SuperBlockingQueue(final int maxNumber, final int ownerId, final DataRepository dataRepository) {
        this.ownerId = ownerId;
        this.maxNumber = maxNumber;
        this.dataRepository = dataRepository;
        queue = new LinkedList<String>();
        privateQueue = new LinkedList<PrivateMessage>();
        databaseNotEmpty = true;
    }


    public void add(final String message) {
        synchronized (this) {
            if (queue.size() < this.maxNumber) {
                queue.add(message);
            }
            this.notify();
        }
    }

    public void addSure(final PrivateMessage message) {
        synchronized (this) {
            if (!databaseNotEmpty) {
                if ((privateQueue.size() < maxNumber)) {
                    privateQueue.add(message);
                    this.notify();
                } else {
                    databaseNotEmpty = true;
                }

            }
        }
    }

    private void loadPrivateMessages() throws InnerChatException, InterruptedException {
        Collection<PrivateMessage> privateMessages = dataRepository.getPrivateMessages(ownerId, lastPrivateMessageId, maxNumber);
        lastPrivateMessageId += privateMessages.size();
        if (privateMessages.size() == 0) {
            databaseNotEmpty = false;
        }
        for (PrivateMessage message : privateMessages) {
            privateQueue.add(message);
        }
    }

    public String take() throws InterruptedException, InnerChatException {
        synchronized (this) {
            while (!Thread.interrupted()) {
                if (queue.isEmpty() && privateQueue.isEmpty() && !databaseNotEmpty) {
                    this.wait();
                }
                if (!privateQueue.isEmpty()) {
                    PrivateMessage message = privateQueue.remove(0);
                    lastPrivateMessageId = message.getId();
                    return message.getMagicRepresentation();
                } else if (databaseNotEmpty) {
                    loadPrivateMessages();
                    if (!privateQueue.isEmpty()) {
                        PrivateMessage message = privateQueue.remove(0);
                        lastPrivateMessageId = message.getId();
                        return message.getMagicRepresentation();
                    }
                } else {
                    return queue.remove(0);
                }
            }
        }
        return null;
    }
}